package com.qf.ability.message.core;

import com.qf.ability.message.handler.DefaultMsgInChannelHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 *
 * 燊
 *
 * author Ken
 * create_time 2022/10/16
 */
@Component
@Slf4j
public class NettyServer {

    private EventLoopGroup master = new NioEventLoopGroup();
    private EventLoopGroup slave = new NioEventLoopGroup();

    private ServerBootstrap serverBootstrap = new ServerBootstrap();

    //服务器Channel
    private Channel serverChannel;

    @Value("${server.port}")
    private int port;

    @Autowired(required = false)
    private List<ChannelHandler> channelHandlers;

    /**
     * 初始化
     */
    @PostConstruct
    public void init(){
        serverBootstrap.group(master, slave)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new HttpServerCodec());
                        pipeline.addLast(new HttpObjectAggregator(1024 * 1024 * 10));
                        pipeline.addLast(new WebSocketServerProtocolHandler("/"));
                        pipeline.addLast(new DefaultMsgInChannelHandler());

                        if (channelHandlers != null) {
                            for (ChannelHandler channelHandler : channelHandlers) {
                                pipeline.addLast(channelHandler);
                            }
                        }
                    }
                });
    }

    /**
     * 服务启动
     */
    public Channel started(){
        ChannelFuture future = serverBootstrap.bind(port).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    log.debug("[netty server started] 服务启动成功 - {}", port);
                } else {
                    log.error("[netty server fail] 服务启动失败", future.cause());
                }
            }
        });

        Channel serverChannel = future.channel();
        System.out.println("获得服务器的Channel：" + serverChannel.getClass().getName());
        serverChannel.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                log.debug("[netty server close] 服务关闭！");
                master.shutdownGracefully();
                slave.shutdownGracefully();
            }
        });
        return serverChannel;
    }
}
